using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using Quotes.ro.bvb.www;

namespace Quotes
{
    public partial class frmMain : Form
    {
        public SystemHotkey systemHotkey1;
        InfoClass info = InfoClass.getInstance();
        bool allCompanies = true;

        public frmMain()
        {
            InitializeComponent();
        }

        public void systemHotkey1_Pressed(object sender, System.EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.WindowState = FormWindowState.Normal;
                this.Activate();
                this.BringToFront();
            }
            else
            {
                this.SendToBack();
                this.WindowState = FormWindowState.Minimized;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            refreshTimer.Interval = InfoClass.refreshTime;
            string timetable = "";
            if (!isStockOpen())
            {
                timetable = "closed";
                InfoClass.refreshTime = 900000;//refreshTimer.Interval = 900000;
            }
            else
            {
                timetable = "open";
                InfoClass.refreshTime = 60000;//refreshTimer.Interval = 60000;
            }
            taskbarIcon.Text = taskbarIcon.Text + timetable;
            MessageBox.Show("The stock exchange is "+timetable+"!\nRefresh time is " + InfoClass.refreshTime / 60000 + " min", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private TypeLevel1[] GetCompanies(string symbol)
        {
            try
            {
                BSEWebServiceDelayed ws = new BSEWebServiceDelayed();
                TypeLevel1[] level1Array;
                if (symbol == InfoClass.ALL)
                {
                    //all companies
                    allCompanies = true;
                    level1Array = ws.TradingDataPerSegment("BSE");
                }
                else
                {   //specific company
                    allCompanies = false;
                    level1Array = ws.TradingDataPerSymbol(symbol);
                }
                return level1Array;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error connecting..", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

        }

        private void FillStocksHashtable(TypeLevel1[] companyArray)
        {
            for (int i = 0; i < companyArray.Length; i++)
            {
                if (companyArray[i].Marketcode == "REGS")
                {
                    info.stocks.Add(companyArray[i].Symbolcode, companyArray[i]);
                }
            }
        }

        private void PopulateListView()
        {
            if (info.stocks.Count > 0)
            {
                foreach (TypeLevel1 company in info.stocks.Values)
                {
                    ListViewItem lvi = new ListViewItem(new string[] { company.Symbolcode, company.ReferencePrice.ToString(), company.PrcChgFromOfficialPrice.ToString(), company.SymbolStatus });
                    lvi.Tag = company.Symbolcode;
                    listView1.Items.Add(lvi);
                    if (company.PrcChgFromOfficialPrice < 0)
                    {
                        lvi.BackColor = Color.Red;
                    }
                    else
                    {
                        lvi.BackColor = Color.Green;
                    }
                }
                alertsToolStripMenuItem.Enabled = true;
            }
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            CleanTextBoxes();
            if (listView1.SelectedItems.Count > 0)
                FillTextBoxes(listView1.SelectedItems[0].Tag.ToString());
        }

        private void CleanTextBoxes()
        {
            lnkSymbol.Text = "";
            txtData.Text = ""; txtPretmediu.Text = ""; txtPretMinim.Text = ""; txtUltimulPret.Text = ""; txtVar.Text = ""; txtVolum.Text = "";
            txtNrTranzactii.Text = ""; txtPretDeschidere.Text = ""; txtPretMaxim.Text = ""; txtValoare.Text = ""; txtVarProcent.Text = "";
        }

        private void FillTextBoxes(string key)
        {
            TypeLevel1 company = (TypeLevel1)info.stocks[key];
            #region writing to textboxes
            lnkSymbol.Text = company.Symbolcode;
            txtData.Text = company.LastTradeTime.ToString();
            txtNrTranzactii.Text = company.Trades.ToString();
            txtPretDeschidere.Text = company.Openprice.ToString();
            txtPretMaxim.Text = company.Highpricecurrent.ToString();
            txtPretmediu.Text = company.Avgprice.ToString();
            txtPretMinim.Text = company.Lowpricecurrent.ToString();
            txtUltimulPret.Text = company.ReferencePrice.ToString();
            txtValoare.Text = company.Value.ToString();
            txtVar.Text = company.NetChgFromOfficialPrice.ToString();
            txtVarProcent.Text = company.PrcChgFromOfficialPrice.ToString();
            txtVolum.Text = company.Volume.ToString();
            #endregion
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void allToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CursorProgressStart();
            backgroundWorker.RunWorkerAsync(InfoClass.ALL);
            //TypeLevel1[] temp = GetCompanies(InfoClass.ALL);
            //info.stocks.Clear();
            //FillStocksHashtable(temp);
            //listView1.Items.Clear();
            //PopulateListView();            
        }

        private void singleCompanyTxt_Click(object sender, EventArgs e)
        {
            if (singleCompanyTxt.Text != "")
            {
                CursorProgressStart();
                backgroundWorker.RunWorkerAsync(singleCompanyTxt.Text);
                menuToolStripMenuItem.HideDropDown();
            }
        }

        private void singleCompanyTxt_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Return)
                singleCompanyTxt_Click(sender, e);
        }

        private string[] SymbolsList()
        {
            string[] tmp = new string[listView1.Items.Count];
            for (int i = 0; i < listView1.Items.Count; i++)
                tmp[i] = listView1.Items[i].SubItems[0].Text;
            return tmp;
        }

        private void multipleCompanyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            StringCollectionEditor editor = new StringCollectionEditor(SymbolsList());
            editor.ShowDialog();
            CursorProgressStart();
            backgroundWorkerMultiple.RunWorkerAsync(editor.symbols);
        }

        private void alertsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmAlert f = new frmAlert();
            f.ShowDialog();
            if (InfoClass.runAlerts)
                refreshTimer_Tick(sender, e);
        }

        private void RunAlerts()
        {
            string alertMessage = "";
            TypeLevel1 tmp = new TypeLevel1();
            foreach (Alert a in info.alerts)
            {
                if (a.Active & info.stocks.ContainsKey(a.Symbol))
                {
                    tmp = (TypeLevel1)info.stocks[a.Symbol];
                    switch (a.Operator)
                    {
                        case OperatorType.bigger:
                            switch (a.NType)
                            {
                                case NumberType.percent:
                                    if (tmp.PrcChgFromOfficialPrice > Convert.ToDouble(a.Value))
                                        alertMessage = a.Symbol + " > " + a.Value + "%";
                                    break;
                                case NumberType.transaction:
                                    if (tmp.Trades > Convert.ToInt64(a.Value))
                                        alertMessage = a.Symbol + " transactions > " + a.Value;
                                    break;
                                case NumberType.value:
                                    if (tmp.ReferencePrice > a.Value)
                                        alertMessage = a.Symbol + " price > " + a.Value;
                                    break;
                                case NumberType.volume:
                                    if (tmp.Volume > Convert.ToInt64(a.Value))
                                        alertMessage = a.Symbol + " volume > " + a.Value;
                                    break;
                            }
                            break;
                        case OperatorType.equal:
                            switch (a.NType)
                            {
                                case NumberType.percent:
                                    if (tmp.PrcChgFromOfficialPrice == Convert.ToDouble(a.Value))
                                        alertMessage = a.Symbol + " = " + a.Value + "%";
                                    break;
                                case NumberType.transaction:
                                    if (tmp.Trades == Convert.ToInt64(a.Value))
                                        alertMessage = a.Symbol + " transactions = " + a.Value;
                                    break;
                                case NumberType.value:
                                    if (tmp.ReferencePrice == a.Value)
                                        alertMessage = a.Symbol + " price = " + a.Value;
                                    break;
                                case NumberType.volume:
                                    if (tmp.Volume == Convert.ToInt64(a.Value))
                                        alertMessage = a.Symbol + " volume = " + a.Value;
                                    break;
                            }
                            break;
                        case OperatorType.less:
                            switch (a.NType)
                            {
                                case NumberType.percent:
                                    if (tmp.PrcChgFromOfficialPrice < Convert.ToDouble(a.Value))
                                        alertMessage = a.Symbol + " < " + a.Value + "%";
                                    break;
                                case NumberType.transaction:
                                    if (tmp.Trades < Convert.ToInt64(a.Value))
                                        alertMessage = a.Symbol + " transactions < " + a.Value;
                                    break;
                                case NumberType.value:
                                    if (tmp.ReferencePrice < a.Value)
                                        alertMessage = a.Symbol + " price < " + a.Value;
                                    break;
                                case NumberType.volume:
                                    if (tmp.Volume < Convert.ToInt64(a.Value))
                                        alertMessage = a.Symbol + " volume < " + a.Value;
                                    break;
                            }
                            break;
                    }
                    if (alertMessage != "")
                        taskbarIcon.ShowBalloonTip(15000, "Alert", alertMessage, ToolTipIcon.Info);
                }
            }
        }

        #region backgroundWorker ALL, single
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            TypeLevel1[] temp = GetCompanies(e.Argument.ToString());
            if (temp != null)
                e.Result = temp;
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Result != null)
            {
                info.stocks.Clear();
                FillStocksHashtable((TypeLevel1[])e.Result);
                listView1.Items.Clear();
                PopulateListView();
            }
            CursorProgressStop();
        }
        #endregion

        #region backgroundWorker multiple
        private void backgroundWorkerMultiple_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                TypeLevel1[] temp;
                info.stocks.Clear();
                string[] symbols = ((string[])e.Argument);
                for (int i = 0; i < symbols.Length; i++)
                {
                    temp = GetCompanies(symbols[i]);
                    FillStocksHashtable(temp);
                }
            }
            catch (NullReferenceException)
            {
            }
        }

        private void backgroundWorkerMultiple_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            listView1.Items.Clear();
            PopulateListView();
            CursorProgressStop();
        }
        #endregion

        #region Cursor&Progressbar
        private void CursorProgressStart()
        {
            this.Cursor = Cursors.WaitCursor;
            listView1.Cursor = Cursors.WaitCursor;
            toolStripProgressBar1.ProgressBar.Show(); statusLabel.Text = "Downloading data..";
        }

        private void CursorProgressStop()
        {
            statusLabel.Text = "Done"; toolStripProgressBar1.ProgressBar.Hide(); statusbarTimer.Start();
            this.Cursor = Cursors.Default;
            listView1.Cursor = Cursors.Default;
            refreshTimer.Start();
            if (!isStockOpen())
                InfoClass.refreshTime = 900000;
            else
                InfoClass.refreshTime = 60000;
        }
        #endregion

        private void statusTimer_Tick(object sender, EventArgs e)
        {
            statusLabel.Text = "";
            statusbarTimer.Stop();
        }

        private void lnkSymbol_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://bvb.ro/ListedCompanies/SecurityDetail.aspx?s=" + lnkSymbol.Text);
        }

        private void refreshTimer_Tick(object sender, EventArgs e)
        {
            if (!isStockOpen())
                InfoClass.refreshTime = 900000;
            else
                InfoClass.refreshTime = 60000;
            if (allCompanies)
                GetCompanies(InfoClass.ALL);
            else
            {
                foreach (ListViewItem lvi in listView1.Items)
                {
                    GetCompanies(lvi.Text);
                }
            }
            RunAlerts();
        }

        #region timetable&DST
        private bool isStockOpen()
        {
            //if (DateTime.UtcNow.DayOfWeek == DayOfWeek.Saturday | DateTime.UtcNow.DayOfWeek == DayOfWeek.Sunday)
            //    return false;
            if (DST())
            {
                if ((TimeSpan.Compare(DateTime.UtcNow.TimeOfDay, new TimeSpan(InfoClass.START_HOUR, InfoClass.START_MIN, 0)) > -1) & (TimeSpan.Compare(DateTime.UtcNow.TimeOfDay, new TimeSpan(InfoClass.STOP_HOUR, InfoClass.STOP_MIN, 0)) < 1))
                    return true;
                return false;
            }
            else
            {
                if ((TimeSpan.Compare(DateTime.UtcNow.TimeOfDay, new TimeSpan(InfoClass.START_HOUR + 1, InfoClass.START_MIN, 0)) > -1) & (TimeSpan.Compare(DateTime.UtcNow.TimeOfDay, new TimeSpan(InfoClass.STOP_HOUR + 1, InfoClass.STOP_MIN, 0)) < 1))
                    return true;
                return false;
            }
        }

        private bool DST()
        {
            return TimeZone.CurrentTimeZone.IsDaylightSavingTime(DateTime.Now);
        }
        #endregion

        private void frmMain_Resize(object sender, EventArgs e)
        {
            switch (this.WindowState)
            {
                case FormWindowState.Normal:
                    this.ShowInTaskbar = true;
                    break;
                case FormWindowState.Minimized:
                    this.ShowInTaskbar = false;
                    break;
            }
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmSettings s = new frmSettings();
            s.ShowDialog();
        }

        private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void taskbarMenu_Opening(object sender, CancelEventArgs e)
        {
            if (this.WindowState == FormWindowState.Normal)
                taskbarMenu.Items[0].Text = "Hide";
            else
                taskbarMenu.Items[0].Text = "Show";
        }

        private void showToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (taskbarMenu.Items[0].Text == "Hide")
            {
                this.WindowState = FormWindowState.Minimized;
            }
            else
            {
                this.WindowState = FormWindowState.Normal;
            }
        }

        private void taskbarIcon_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (this.WindowState == FormWindowState.Minimized)
                {
                    this.WindowState = FormWindowState.Normal;
                }
                else
                {
                    this.WindowState = FormWindowState.Minimized;
                }
            }
        }
    }
}